home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Maclife 157
/
MACLIFE157-2001-09.ISO.7z
/
MACLIFE157-2001-09.ISO
/
Linux
/
MacOS Tools
/
BootX 1.2.2
/
Sources
/
src
/
miboot
/
miBoot_low.c
< prev
next >
Wrap
C/C++ Source or Header
|
2001-07-23
|
18KB
|
576 lines
#include <Types.h>
#include <CodeFragments.h>
#include <MixedMode.h>
#include <OSUtils.h>
#include <Processes.h>
#include <Traps.h>
#include <ShutDown.h>
#include <A4Stuff.h>
#include <Video.h>
#include <Palettes.h>
#include <SCSI.h>
#include <Power.h>
#include <Gestalt.h>
#include <LowMem.h>
#include <Displays.h>
#include "LowLevelBoot.h"
#include "BootX.h"
#include "debug_text.h"
#include "uLibc.h"
#define LINUX_LOGO_COLORS 214
#define CLOSE_VIDEO_DRIVERS 0
#define FAKE_DEBUGGER 0
#define FORCE_SCSI_ON 0
#define DO_POWER_MANAGEMENT 0
// This code will do the actual boot
// Prototypes
static void PrepareDisplay(boot_infos_t *bi);
static void RemoveAnyHWCursor(short driverRefNum);
static void SetDefaultLinuxCTable(short driverRefNum);
static void GetColorMap(boot_infos_t* bi, GDHandle device);
static void SwitchTo8Bits(boot_infos_t* bi, GDHandle gDevice);
static void ForceUnmountAllVolumes(void);
static Boolean TrapAvailable(short theTrap);
extern Ptr get_physical(void* ptr);
extern unsigned char linux_logo_red[];
extern unsigned char linux_logo_green[];
extern unsigned char linux_logo_blue[];
extern dt_context* dct;
inline asm void
DisableInterrupts(void)
{
ori.w #0x700, sr
}
// Entry point called by BootX to install the shutdown proc.
pascal void
low_boot(PPCRegisterList* regList, boot_infos_t* bi, void* ppc_glue, UInt32 flags, dt_context* in_dct)
{
// EventRecord event;
// EnterCodeResource();
// SetZone(SystemZone());
// Unmounts all volumes is not done by shudown proc
if (LMGetVCBQHdr()->qHead) {
dt_printf(dct, "Unmounting volumes...¥n");
ForceUnmountAllVolumes();
}
dt_printf(dct, "Preparing display...¥n");
// Prepare displays (setup colormaps for 8 bits displays, remove HW cursors, ...)
PrepareDisplay(bi);
// Let MacOS think we are a debugger and switch 68k emulator to supervisor first
#if FAKE_DEBUGGER
DebuggerEnter();
#endif
// Put the emulator in supervisor mode
dt_printf(dct, "Entering 68k supervisor...¥n");
EnterSupervisorMode();
#if FAKE_DEBUGGER
// Poll until no more OS events in the queue (safety)
do {
if (event.what == nullEvent)
break;
DebuggerPoll();
}
while(GetOSEvent(everyEvent, &event) != 0);
#endif
// New BootX no longer care about logical display.
bi->logicalDisplayBase = bi->dispDeviceBase;
// Switch emulator interrupts off
DisableInterrupts();
// Reset some pieces of hardware
if (ppc_glue)
((pascal void(*)(dt_context*,boot_infos_t*))ppc_glue)(dct, bi);
// tempo
if (dct->visible) {
UInt32 i;
dt_printf(dct, "waiting a little bit so you can read all that stuff ...¥n");
for(i=0;i<0x10000000; i++) {
(void)*((volatile char *)(0));
}
}
// Enter PPC supervisor (and boot kernel)
dt_printf(dct, "Entering PPC supervisor...¥n");
EnterPPCSupervisor(regList);
// Should never reach this point
#if FAKE_DEBUGGER
DebuggerExit();
#endif
}
// This piece of code will unmount all volumes, including the system disk and
// volumes with currently opened files.
void
ForceUnmountAllVolumes(void)
{
QHdrPtr vcbQueue;
VCBPtr vcb;
vcbQueue = LMGetVCBQHdr();
while((vcb = (VCBPtr)vcbQueue->qHead) != NULL) {
ParamBlockRec pb;
memset(&pb, 0, sizeof(ParamBlockRec));
pb.volumeParam.ioVRefNum = vcb->vcbVRefNum;
pb.volumeParam.ioNamePtr = NULL;
PBUnmountVolImmed(&pb);
}
}
// This routine will walk thru all MacOS displays, remove
// hardware cursors and set colormaps to std linux colors for each
// indexed device.
void
PrepareDisplay(boot_infos_t *bi)
{
#if CLOSE_VIDEO_DRIVERS
static short sDriverList[16];
static Str255 sCFMError;
CFragConnectionID driverLoaderLib;
Ptr driverLoaderMain;
int driver_count, i;
#endif
OSErr err;
GDHandle device;
// We get default display infos.
device = GetMainDevice();
bi->dispDeviceRect[0] = (**(**device).gdPMap).bounds.left;
bi->dispDeviceRect[1] = (**(**device).gdPMap).bounds.top;
bi->dispDeviceRect[2] = (**(**device).gdPMap).bounds.right;
bi->dispDeviceRect[3] = (**(**device).gdPMap).bounds.bottom;
bi->dispDeviceDepth = (**(**device).gdPMap).pixelSize;
bi->dispDeviceBase = (UInt8 *)get_physical((UInt8 *)(**(**device).gdPMap).baseAddr);
bi->dispDeviceRowBytes = (**(**device).gdPMap).rowBytes & 0x3FFF;
bi->dispDeviceRegEntryOffset = NULL; // Not impl. yet
bi->logicalDisplayBase = (UInt8 *)(**(**device).gdPMap).baseAddr;
// We loop all displays
device = GetDeviceList();
#if CLOSE_VIDEO_DRIVERS
driver_count = 0;
#endif
while(device)
{
if (TestDeviceAttribute(device, screenDevice) && !TestDeviceAttribute(device, noDriver))
{
short refNum = (**device).gdRefNum;
#if CLOSE_VIDEO_DRIVERS
int found;
// Add this driver to the list if it was not already in
found=0;
for(i=0; i<driver_count; i++)
if (sDriverList[i] == refNum)
{
found = true;
break;
}
if (!found)
sDriverList[driver_count++] = refNum;
#endif
// We need to switch to 8 bits since offb.c cannot handle anything else
// yet. (Only for the main device)
if (TestDeviceAttribute(device, mainScreen) && ((**(**device).gdPMap).pixelSize < 8))
SwitchTo8Bits(bi, device);
// If the device has indexed colors, we install the standard Linux colormap
if ((**device).gdType == clutType)
SetDefaultLinuxCTable(refNum);
// We try to blank the hardware cursor. Note that most devices will just make
// a transparent cursor, so it's a good thing, when not using a full-featured
// linux video driver, to avoid overriding the framebuffer outside of the
// defined rectangle. The border might actually contain the cursor.
RemoveAnyHWCursor(refNum);
}
device = GetNextDevice(device);
}
// Get color map for main device
GetColorMap(bi, GetMainDevice());
#if CLOSE_VIDEO_DRIVERS
err = GetSharedLibrary("¥pDriverLoaderLib", kAnyCFragArch, kReferenceCFrag,
&driverLoaderLib, &driverLoaderMain, sCFMError);
if (err == noErr)
{
CFragSymbolClass removeDrvrClass;
Ptr removeDrvrProc;
err = FindSymbol(driverLoaderLib, "¥pRemoveDriver", &removeDrvrProc, &removeDrvrClass);
if (err == noErr)
{
enum
{
uppRemoveDriverProcInfo = kCStackBased
| RESULT_SIZE(SIZE_CODE(sizeof(OSErr)))
| STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(short)))
| STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Boolean)))
};
UniversalProcPtr removeDriverUPP =
NewRoutineDescriptorTrap( (ProcPtr)removeDrvrProc,
uppRemoveDriverProcInfo,
kPowerPCISA);
// Close all video drivers
for (i=0; i<driver_count; i++)
{
CloseDriver(sDriverList[i]);
((OSErr (*)(short, Boolean))(removeDriverUPP))(sDriverList[i], false);
}
}
}
#endif
}
// Gather some infos about the current MacOS main display. This function
// was originally in BootX.c (get_display_infos)
void
GetColorMap(boot_infos_t* bi, GDHandle device)
{
if ((**device).gdType == clutType)
{
unsigned short* colors = (unsigned short*)(((unsigned long)bi) + bi->dispDeviceColorsOffset);
CntrlParam param;
VDSetEntryRecord hwGetEntry;
int i;
OSErr err;
static ColorSpec sTempColors[256];
memset(¶m, 0, sizeof(CntrlParam));
memset(&hwGetEntry, 0, sizeof(VDSetEntryRecord));
param.csCode = cscGetEntries;
param.ioCRefNum = (**device).gdRefNum;
hwGetEntry.csTable = sTempColors;
hwGetEntry.csStart = 0;
hwGetEntry.csCount = 255; // csCount is 0 based !!
*((VDSetEntryRecord **)¶m.csParam[0]) = &hwGetEntry;
err = PBStatusSync((ParmBlkPtr)¶m);
if (err == noErr)
for (i=0; i<256; i++)
{
*(colors++) = sTempColors[i].rgb.red;
*(colors++) = sTempColors[i].rgb.green;
*(colors++) = sTempColors[i].rgb.blue;
}
else
bi->dispDeviceColorsOffset = 0;
} else
bi->dispDeviceColorsOffset = 0;
}
// Here, we switch the display to 8 bits using driver calls
void
SwitchTo8Bits(boot_infos_t* bi, GDHandle gDevice)
{
// Lookup the modes supported by he video driver, looking for 8 bits
CntrlParam param;
VDVideoParametersInfoRec hwVideoParams;
VDPageInfo hwModeSet;
VDSwitchInfoRec hwModeGet;
VPBlock hwVP;
short i;
short foundDepth;
OSErr err;
memset(¶m, 0, sizeof(CntrlParam));
memset(&hwModeSet, 0, sizeof(VDPageInfo));
memset(&hwModeGet, 0, sizeof(VDSwitchInfoRec));
param.csCode = cscGetCurMode;
param.ioCRefNum = (**gDevice).gdRefNum;
*((VDSwitchInfoRec **)¶m.csParam[0]) = &hwModeGet;
err = PBStatusSync((ParmBlkPtr)¶m);
if (err != noErr)
return;
foundDepth = 0;
for (i=kDepthMode1; i<=kDepthMode6; i++)
{
memset(&hwVideoParams, 0, sizeof(VDVideoParametersInfoRec));
memset(&hwVP, 0, sizeof(VPBlock));
hwVideoParams.csDisplayModeID = hwModeGet.csData;
hwVideoParams.csDepthMode = i;
hwVideoParams.csVPBlockPtr = &hwVP;
param.csCode = cscGetVideoParameters;
param.ioCRefNum = (**gDevice).gdRefNum;
*((VDVideoParametersInfoRec **)¶m.csParam[0]) = &hwVideoParams;
err = PBStatusSync((ParmBlkPtr)¶m);
if (err == noErr)
{
if (hwVP.vpPixelSize == 8)
{
foundDepth = i;
break;
}
}
}
if (foundDepth != 0)
{
hwModeSet.csMode = foundDepth;
hwModeSet.csPage = 0;
param.csCode = cscSetMode;
param.ioCRefNum = (**gDevice).gdRefNum;
*((VDPageInfo **)¶m.csParam[0]) = &hwModeSet;
err = PBControlSync((ParmBlkPtr)¶m);
if (err == noErr)
{
(**gDevice).gdType = clutType;
(**gDevice).gdMode = foundDepth;
bi->dispDeviceDepth = hwVP.vpPixelSize;
bi->logicalDisplayBase = (UInt8 *)hwModeSet.csBaseAddr;
bi->dispDeviceBase = (UInt8 *)get_physical((UInt8 *)hwModeSet.csBaseAddr);
bi->dispDeviceRowBytes = hwVP.vpRowBytes & 0x3FFF;
}
}
}
// Ask the display driver if it supports hardware cursor and remove it.
void
RemoveAnyHWCursor(short driverRefNum)
{
CntrlParam param;
VDSupportsHardwareCursorRec hwCursQuery;
VDDrawHardwareCursorRec hwCursSet;
OSErr err;
void* genericPtr;
memset(¶m, 0, sizeof(CntrlParam));
memset(&hwCursQuery, 0, sizeof(VDSupportsHardwareCursorRec));
memset(&hwCursSet, 0, sizeof(VDDrawHardwareCursorRec));
param.csCode = cscSupportsHardwareCursor;
param.ioCRefNum = driverRefNum;
*((VDSupportsHardwareCursorRec **)¶m.csParam[0]) = &hwCursQuery;
err = PBStatusSync((ParmBlkPtr)¶m);
if (err != noErr)
return;
if (!hwCursQuery.csSupportsHardwareCursor)
return;
memset(¶m, 0, sizeof(CntrlParam));
memset(&hwCursSet, 0, sizeof(VDDrawHardwareCursorRec));
param.csCode = cscDrawHardwareCursor;
param.ioCRefNum = driverRefNum;
*((VDDrawHardwareCursorRec **)¶m.csParam[0]) = &hwCursSet;
err = PBControlSync((ParmBlkPtr)¶m);
}
// Install the linux default color map. We use direct driver calls since the
// Palette Manager may prevent us from setting reserved MacOS colors.
void
SetDefaultLinuxCTable(short driverRefNum)
{
static ColorSpec sDefaultLinuxColors[] =
{ 0, { 0x0000, 0x0000, 0x0000 },
1, { 0x0000, 0x0000, 0xaaaa },
2, { 0x0000, 0xaaaa, 0x0000 },
3, { 0x0000, 0xaaaa, 0xaaaa },
4, { 0xaaaa, 0x0000, 0x0000 },
5, { 0xaaaa, 0x0000, 0xaaaa },
6, { 0xaaaa, 0xaaaa, 0x0000 },
7, { 0xaaaa, 0xaaaa, 0xaaaa },
8, { 0x5555, 0x5555, 0x5555 },
9, { 0x5555, 0x5555, 0xffff },
10, { 0x5555, 0xffff, 0x5555 },
11, { 0x5555, 0xffff, 0xffff },
12, { 0xffff, 0x5555, 0x5555 },
13, { 0xffff, 0x5555, 0xffff },
14, { 0xffff, 0xffff, 0x5555 },
15, { 0xffff, 0xffff, 0xffff } };
CntrlParam param;
VDSetEntryRecord hwSetEntry;
OSErr err;
unsigned long temp;
ColorSpec* logo_colors;
int i;
memset(¶m, 0, sizeof(CntrlParam));
memset(&hwSetEntry, 0, sizeof(VDSetEntryRecord));
param.csCode = cscSetEntries;
param.ioCRefNum = driverRefNum;
hwSetEntry.csTable = sDefaultLinuxColors;
hwSetEntry.csStart = 0;
hwSetEntry.csCount = 15; // csCount is 0 based !!
*((VDSetEntryRecord **)¶m.csParam[0]) = &hwSetEntry;
err = PBControlSync((ParmBlkPtr)¶m);
logo_colors = (ColorSpec *)NewPtrSys(sizeof(ColorSpec) * LINUX_LOGO_COLORS);
if (logo_colors == NULL)
goto failed;
for (i=0; i<LINUX_LOGO_COLORS; i++)
{
logo_colors[i].value = i + 32;
logo_colors[i].rgb.red = (linux_logo_red[i] << 8) | linux_logo_red[i];
logo_colors[i].rgb.green = (linux_logo_green[i] << 8) | linux_logo_green[i];
logo_colors[i].rgb.blue = (linux_logo_blue[i] << 8) | linux_logo_blue[i];
}
param.csCode = cscSetEntries;
param.ioCRefNum = driverRefNum;
hwSetEntry.csTable = logo_colors;
hwSetEntry.csStart = 32;
hwSetEntry.csCount = LINUX_LOGO_COLORS-1; // csCount is 0 based !!
*((VDSetEntryRecord **)¶m.csParam[0]) = &hwSetEntry;
err = PBControlSync((ParmBlkPtr)¶m);
DisposePtr((Ptr)logo_colors);
failed:
// Leave some time for the VBL to update the palette
Delay(10, &temp);
}
/*
* TrapAvailable (see Inside Mac VI 3-8)
*/
#define NumToolboxTraps() ( ¥
(NGetTrapAddress(_InitGraf, ToolTrap) ¥
== NGetTrapAddress(0xAA6E, ToolTrap)) ¥
? 0x200 : 0x400 ¥
)
#define GetTrapType(theTrap) ( ¥
(((theTrap) & 0x0800) != 0) ? ToolTrap : OSTrap ¥
)
static Boolean
TrapAvailable(short theTrap)
{
TrapType trapType;
trapType = GetTrapType(theTrap);
if (trapType == ToolTrap) {
theTrap &= 0x07FF;
if (theTrap >= NumToolboxTraps())
theTrap = _Unimplemented;
}
return (
NGetTrapAddress(theTrap, trapType)
!= NGetTrapAddress(_Unimplemented, ToolTrap)
);
}
unsigned char linux_logo_red[] = {
0x02, 0x9E, 0xE9, 0xC4, 0x50, 0xC9, 0xC4, 0xE9,
0x65, 0xE3, 0xC2, 0x25, 0xA4, 0xEC, 0x90, 0xA6,
0xC4, 0x6A, 0xD1, 0xF3, 0x12, 0xED, 0xA0, 0xC2,
0xB8, 0xD5, 0xDB, 0xD2, 0x3E, 0x16, 0xEB, 0x54,
0xA9, 0xCD, 0xF5, 0x0A, 0xBA, 0xB3, 0xDC, 0x74,
0xCE, 0xF6, 0xD3, 0xC5, 0xEA, 0xB8, 0xED, 0x5E,
0xE5, 0x26, 0xF4, 0xA9, 0x82, 0x94, 0xE6, 0x38,
0xF2, 0x0F, 0x7F, 0x49, 0xE5, 0xF4, 0xD3, 0xC3,
0xC2, 0x1E, 0xD5, 0xC6, 0xA4, 0xFA, 0x0A, 0xBA,
0xD4, 0xEB, 0xEA, 0xEC, 0xA8, 0xBC, 0xB4, 0xDC,
0x84, 0xE4, 0xCE, 0xEC, 0x92, 0xCD, 0xDC, 0x8B,
0xCC, 0x1E, 0xF6, 0xB2, 0x60, 0x2A, 0x96, 0x52,
0x0F, 0xBD, 0xFA, 0xCC, 0xB8, 0x7A, 0x4C, 0xD2,
0x06, 0xEF, 0x44, 0x64, 0xF4, 0xBA, 0xCE, 0xE6,
0x8A, 0x6F, 0x3C, 0x70, 0x7C, 0x9C, 0xBA, 0xDF,
0x2C, 0x4D, 0x3B, 0xCA, 0xDE, 0xCE, 0xEE, 0x46,
0x6A, 0xAC, 0x96, 0xE5, 0x96, 0x7A, 0xBA, 0xB6,
0xE2, 0x7E, 0xAA, 0xC5, 0x96, 0x9E, 0xC2, 0xAA,
0xDA, 0x35, 0xB6, 0x82, 0x88, 0xBE, 0xC2, 0x9E,
0xB4, 0xD5, 0xDA, 0x9C, 0xA0, 0xD0, 0xA8, 0xC7,
0x72, 0xF2, 0xDB, 0x76, 0xDC, 0xBE, 0xAA, 0xF4,
0x87, 0x2F, 0x53, 0x8E, 0x36, 0xCE, 0xE6, 0xCA,
0xCB, 0xE4, 0xD6, 0xAA, 0x42, 0x5D, 0xB4, 0x59,
0x1C, 0xC8, 0x96, 0x6C, 0xDA, 0xCE, 0xE6, 0xCB,
0x96, 0x16, 0xFA, 0xBE, 0xAE, 0xFE, 0x6E, 0xD6,
0xCE, 0xB6, 0xE5, 0xED, 0xDB, 0xDC, 0xF4, 0x72,
0x1F, 0xAE, 0xE6, 0xC2, 0xCA, 0xC4
};
unsigned char linux_logo_green[] = {
0x02, 0x88, 0xC4, 0x85, 0x44, 0xA2, 0xA8, 0xE5,
0x65, 0xA6, 0xC2, 0x24, 0xA4, 0xB4, 0x62, 0x86,
0x94, 0x44, 0xD2, 0xB6, 0x12, 0xD4, 0x73, 0x96,
0x92, 0x95, 0xB2, 0xC2, 0x36, 0x0E, 0xBC, 0x54,
0x75, 0xA5, 0xF5, 0x0A, 0xB2, 0x83, 0xC2, 0x74,
0x9B, 0xBD, 0xA2, 0xCA, 0xDA, 0x8C, 0xCB, 0x42,
0xAC, 0x12, 0xDA, 0x7B, 0x54, 0x94, 0xD2, 0x24,
0xBE, 0x06, 0x65, 0x33, 0xBB, 0xBC, 0xAB, 0x8C,
0x92, 0x1E, 0x9B, 0xB6, 0x6E, 0xFB, 0x04, 0xA2,
0xC8, 0xBD, 0xAD, 0xEC, 0x92, 0xBC, 0x7B, 0x9D,
0x84, 0xC4, 0xC4, 0xB4, 0x6C, 0x93, 0xA3, 0x5E,
0x8D, 0x13, 0xD6, 0x82, 0x4C, 0x2A, 0x7A, 0x5A,
0x0D, 0x82, 0xBB, 0xCC, 0x8B, 0x6A, 0x3C, 0xBE,
0x06, 0xC4, 0x44, 0x45, 0xDB, 0x96, 0xB6, 0xDE,
0x8A, 0x4D, 0x3C, 0x5A, 0x7C, 0x9C, 0xAA, 0xCB,
0x1C, 0x4D, 0x2E, 0xB2, 0xBE, 0xAA, 0xDE, 0x3E,
0x6A, 0xAC, 0x82, 0xE5, 0x72, 0x62, 0x92, 0x9E,
0xCA, 0x4A, 0x8E, 0xBE, 0x86, 0x6B, 0xAA, 0x9A,
0xBE, 0x34, 0xAB, 0x76, 0x6E, 0x9A, 0x9E, 0x62,
0x76, 0xCE, 0xD3, 0x92, 0x7C, 0xB8, 0x7E, 0xC6,
0x5E, 0xE2, 0xC3, 0x54, 0xAA, 0x9E, 0x8A, 0xCA,
0x63, 0x2D, 0x3B, 0x8E, 0x1A, 0x9E, 0xC2, 0xA6,
0xCB, 0xDC, 0xD6, 0x8E, 0x26, 0x5C, 0xB4, 0x45,
0x1C, 0xB8, 0x6E, 0x4C, 0xBC, 0xAE, 0xD6, 0x92,
0x63, 0x16, 0xF6, 0x8C, 0x7A, 0xFE, 0x6E, 0xBA,
0xC6, 0x86, 0xAA, 0xAE, 0xDB, 0xA4, 0xD4, 0x56,
0x0E, 0x6E, 0xB6, 0xB2, 0xBE, 0xBE
};
unsigned char linux_logo_blue[] = {
0x04, 0x28, 0x10, 0x0B, 0x14, 0x14, 0x74, 0xC7,
0x64, 0x0E, 0xC3, 0x24, 0xA4, 0x0C, 0x10, 0x20,
0x0D, 0x04, 0xD1, 0x0D, 0x13, 0x22, 0x0A, 0x40,
0x14, 0x0C, 0x11, 0x94, 0x0C, 0x08, 0x0B, 0x56,
0x09, 0x47, 0xF4, 0x0B, 0x9C, 0x07, 0x54, 0x74,
0x0F, 0x0C, 0x0F, 0xC7, 0x6C, 0x14, 0x14, 0x11,
0x0B, 0x04, 0x12, 0x0C, 0x05, 0x94, 0x94, 0x0A,
0x34, 0x09, 0x14, 0x08, 0x2F, 0x15, 0x19, 0x11,
0x28, 0x0C, 0x0B, 0x94, 0x08, 0xFA, 0x08, 0x7C,
0xBC, 0x15, 0x0A, 0xEC, 0x64, 0xBB, 0x0A, 0x0C,
0x84, 0x2C, 0xA0, 0x15, 0x10, 0x0D, 0x0B, 0x0E,
0x0A, 0x07, 0x10, 0x3C, 0x24, 0x2C, 0x28, 0x5C,
0x0A, 0x0D, 0x0A, 0xC1, 0x22, 0x4C, 0x10, 0x94,
0x04, 0x0F, 0x45, 0x08, 0x31, 0x54, 0x3C, 0xBC,
0x8C, 0x09, 0x3C, 0x18, 0x7C, 0x9C, 0x7C, 0x91,
0x0C, 0x4D, 0x17, 0x74, 0x0C, 0x48, 0x9C, 0x3C,
0x6A, 0xAC, 0x5C, 0xE3, 0x29, 0x3C, 0x2C, 0x7C,
0x6C, 0x04, 0x14, 0xA9, 0x74, 0x07, 0x2C, 0x74,
0x4C, 0x34, 0x97, 0x5C, 0x38, 0x0C, 0x5C, 0x04,
0x0C, 0xBA, 0xBC, 0x78, 0x18, 0x88, 0x24, 0xC2,
0x3C, 0xB4, 0x87, 0x0C, 0x14, 0x4C, 0x3C, 0x10,
0x17, 0x2C, 0x0A, 0x8C, 0x04, 0x1C, 0x44, 0x2C,
0xCD, 0xD8, 0xD4, 0x34, 0x0C, 0x5B, 0xB4, 0x1E,
0x1D, 0xAC, 0x24, 0x18, 0x20, 0x5C, 0xB4, 0x1C,
0x09, 0x14, 0xFC, 0x0C, 0x10, 0xFC, 0x6C, 0x7C,
0xB4, 0x1C, 0x15, 0x17, 0xDB, 0x18, 0x21, 0x24,
0x04, 0x04, 0x44, 0x8C, 0x8C, 0xB7
};